﻿﻿﻿﻿﻿﻿﻿using DeviceCommons.DataHandling;
using DeviceCommons.DeviceMessages.Models;
using DeviceCommons.Validation;

namespace DeviceCommons.DeviceMessages.Abstractions
{
    public abstract class AbstractMessageParser<T> : AbstractMessage<T>, IMessageParser<T> where T : IBase
    {
        protected AbstractMessageParser(T t) : base(t)
        {
        }

        public virtual Func<string, string>? DecryptFunc { get; set; }
        public virtual Func<byte[], byte[]>? DecompressFunc { get; set; }
        public abstract T Parser(ReadOnlySpan<byte> bytes);

        public virtual T Parser(string data)
        {
            return Parser(data, null);
        }

        /// <summary>
        /// 解析十六进制字符串消息，支持自定义解密密码
        /// 优先级：DecryptFunc > 提供的密码 > 默认密码
        /// </summary>
        /// <param name="data">十六进制字符串</param>
        /// <param name="password">解密密码，null时使用默认密码</param>
        /// <returns>解析后的消息对象</returns>
        public virtual T Parser(string data, string? password)
        {
            // 前置验证
            DeviceMessageValidator.ValidateHexString(data, nameof(data));
            if (password != null)
            {
                DeviceMessageValidator.ValidatePassword(password, nameof(password));
            }
            
            IsEncryptOrCompress(data, out string dataTemp, out bool isEncrypt, out bool isCompress);
            if (isEncrypt)
            {
                if (DecryptFunc != null)
                {
                    // 优先使用预设的解密函数
                    dataTemp = DecryptFunc(dataTemp);
                }
                else if (!string.IsNullOrEmpty(password))
                {
                    // 使用提供的密码进行AES解密
                    dataTemp = DeviceMessageUtilities.AES.Value.Decrypt(dataTemp, password);
                }
                else
                {
                    // 使用默认密码进行AES解密
                    dataTemp = DeviceMessageUtilities.AES.Value.Decrypt(dataTemp, DeviceMessageArrayPool.DefaultAedPassword);
                }
            }

            byte[] bytes;
            if (isCompress)
            {
                DecompressFunc ??= DeviceMessageUtilities.GZIP.Decompress;
                bytes = DecompressFunc(Convert.FromHexString(dataTemp));
            }
            else
            {
                bytes = Convert.FromHexString(dataTemp);
            }

            return Parser(bytes);
        }

        public virtual async Task<T> ParserAsync(byte[] bytes, CancellationToken cancellationToken = default) =>
            await ParserInternalAsync(bytes, cancellationToken).ConfigureAwait(false);

        public virtual async Task<T> ParserAsync(string data, CancellationToken cancellationToken = default)
        {
            return await ParserAsync(data, null, cancellationToken).ConfigureAwait(false);
        }

        /// <summary>
        /// 异步解析十六进制字符串消息，支持自定义解密密码
        /// 优先级：DecryptFunc > 提供的密码 > 默认密码
        /// </summary>
        /// <param name="data">十六进制字符串</param>
        /// <param name="password">解密密码，null时使用默认密码</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>解析后的消息对象</returns>
        public virtual async Task<T> ParserAsync(string data, string? password, CancellationToken cancellationToken = default)
        {
            IsEncryptOrCompress(data, out string dataTemp, out bool isEncrypt, out bool isCompress);

            if (isEncrypt)
            {
                if (DecryptFunc != null)
                {
                    // 优先使用预设的解密函数
                    dataTemp = await Task.Run(() => DecryptFunc(dataTemp), cancellationToken).ConfigureAwait(false);
                }
                else if (!string.IsNullOrEmpty(password))
                {
                    // 使用提供的密码进行AES解密
                    dataTemp = await Task.Run(() => DeviceMessageUtilities.AES.Value.Decrypt(dataTemp, password), cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    // 使用默认密码进行AES解密
                    dataTemp = await Task.Run(() => DeviceMessageUtilities.AES.Value.Decrypt(dataTemp, DeviceMessageArrayPool.DefaultAedPassword), cancellationToken).ConfigureAwait(false);
                }
            }

            byte[] finalBytes;
            if (isCompress)
            {
                DecompressFunc ??= DeviceMessageUtilities.GZIP.Decompress;
                finalBytes = DecompressFunc(Convert.FromHexString(dataTemp));
            }
            else
            {
                finalBytes = Convert.FromHexString(dataTemp);
            }

            return await ParserInternalAsync(finalBytes, cancellationToken).ConfigureAwait(false);
        }

        protected virtual async Task<T> ParserInternalAsync(byte[] bytes, CancellationToken cancellationToken = default)
        {
            return await Task.Run(() => Parser(bytes), cancellationToken).ConfigureAwait(false);
        }

        public static void IsEncryptOrCompress(string sourceData, out string data, out bool isEncrypt, out bool isCompress)
        {
            var decSplit = sourceData.Split('|');
            data = decSplit[0];
            isEncrypt = false;
            isCompress = false;
            if (decSplit.Length > 1)
            {
                var states = decSplit[0].Split(',');
                data = decSplit[1];
                isEncrypt = states[0].ToLower().Equals("enc");
                isCompress = states[1].ToLower().Equals("gzip");
            }
        }
    }
}
